package ute.mvc.controller.portal.lecturer;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;

import javax.servlet.ServletContext;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;

import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import ute.mvc.dto.ClassDTO;
import ute.mvc.dto.EditAssignmentDTO;
import ute.mvc.dto.NewAssignmentDTO;
import ute.mvc.dto.SubmittedAssignmentDTO;
import ute.mvc.model.Assignment;
import ute.mvc.model.MyFile;
import ute.mvc.model.MyClass;
import ute.mvc.model.MyFile;
import ute.mvc.model.OpenCourse;
import ute.mvc.model.OpenCourse_Subject;
import ute.mvc.model.SubmittedAssignment;
import ute.mvc.model.TestAndQuizz;
import ute.mvc.model.User;
import ute.mvc.service.AssignmentService;
import ute.mvc.service.Course_SubjectService;
import ute.mvc.service.FileService;
import ute.mvc.service.OpenCourseService;
import ute.mvc.service.SubmittedAssignmentService;
import ute.mvc.service.UserService;
import ute.mvc.util.FileUtil;
import ute.mvc.util.IdUtil;
import ute.mvc.util.JsonObject;

@Controller
@RequestMapping(value = "/lecturer/{lecturerId}/{openCourseId}/{subjectId}/assignment")
public class AssignmentController {

	@Autowired
	Course_SubjectService course_SubjectService;
	@Autowired
	FileService fileService;
	@Autowired
	SessionFactory sessionFactory;
	@Autowired
	OpenCourseService openCourseService;
	@Autowired
	Course_SubjectService courseSubjectService;
	@Autowired
	UserService userService;
	@Autowired
	AssignmentService assignmentService;
	@Autowired
	SubmittedAssignmentService submittedAssigmentService;
	@Autowired
	ApplicationContext applicationContext;

	@RequestMapping(value = "/", method = RequestMethod.GET)
	public String getListAssignment() {

		return "lecturer_assignment_list";
	}

	@RequestMapping(value = "/add", method = RequestMethod.GET)
	public String getNewAssignment(Model model) {
		NewAssignmentDTO newAssignmentDTO = new NewAssignmentDTO();
		model.addAttribute("newAssignmentDTO", newAssignmentDTO);

		return "lecturer_assignment_add";
	}

	@RequestMapping(value = "/add", method = RequestMethod.POST)
	public String saveNewAssignment(
			@PathVariable int lecturerId,
			@PathVariable String openCourseId,
			@PathVariable String subjectId,
			@Valid @ModelAttribute("newAssignmentDTO") NewAssignmentDTO newAssignmentDTO,
			BindingResult result, Model model, HttpServletRequest request) {

		if (result.hasErrors())
			return "lecturer_assignment_add";
		if (newAssignmentDTO.getEndDate().compareTo(
				newAssignmentDTO.getStartDay()) <= 0) {
			result.rejectValue("endDate", "wrongendate");
			return "lecturer_assignment_add";
		}

		User lecturer = userService.getUserById(lecturerId);
		String id = openCourseId + "_" + subjectId;
		OpenCourse_Subject subject = courseSubjectService.getCourse_Subject(id);
		String maxId = assignmentService.getMaxIdInOpenCourseSubject(subject);
		String newId = IdUtil.getNewTestIdInOpenCourseSubject(maxId);

		// add new Assignment
		Assignment assignment = new Assignment();
		assignment.setAssignmentId(id + "_" + newId);
		assignment.setAssignmentName(newAssignmentDTO.getAssignmentName());
		assignment.setDescription(newAssignmentDTO.getDescription());
		assignment.setEndDate(newAssignmentDTO.getEndDate());
		assignment.setLecturer(lecturer);
		assignment.setMaxPoint(newAssignmentDTO.getMaxPoint());
		assignment.setOpenCourse_Subject(subject);
		assignment.setStartDay(newAssignmentDTO.getStartDay());
		assignment.setTimeSubmitAllow(newAssignmentDTO.getTimeSubmitAllow());

		// set list class for assignment
		OpenCourse openCourse = openCourseService
				.getOpenCourseById(openCourseId);
		List<MyClass> listClass = new ArrayList<MyClass>(
				openCourse.getListClass());
		assignment.setListClass(listClass);

		String fileName = newAssignmentDTO.getFile().getOriginalFilename();
		if (!"".equals(fileName)) {
			// add new file to DB
			MyFile file = new MyFile();
			file.setFileName(fileName);
			fileService.addFile(file);

			// write this file to directory
			MultipartFile mFile = newAssignmentDTO.getFile();

			try {
				mFile.transferTo(new java.io.File(FileUtil.getFileLocation(applicationContext) + "\\" + file.getFileId()));
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

			// set this file to new Assignment
			assignment.setFile(file);
		}
		assignmentService.addAssignment(assignment);
		return "redirect:";
	}

	@RequestMapping(value = "/info/{assignmentId}", method = RequestMethod.GET)
	public String getAssignmentInfo(@PathVariable String assignmentId,
			@PathVariable String openCourseId, @PathVariable String subjectId,
			Model model) {
		System.out.println("get assignment's information");
		Assignment assignment = assignmentService
				.getAssignmentById(assignmentId);

		model.addAttribute("assignment", assignment);
		model.addAttribute("file", assignment.getFile());

		return "lecturer_assignment_info";
	}

	@RequestMapping(value = "/edit/{assignmentId}", method = RequestMethod.GET)
	public String getEditAssignment(@PathVariable String assignmentId,
			@PathVariable String openCourseId, @PathVariable String subjectId,
			Model model) {

		System.out.println("Get Edit Assignment");

		EditAssignmentDTO editAssignmentDTO = assignmentService
				.getEditDTOByAssignmentId(assignmentId);
		model.addAttribute("editAssignmentDTO", editAssignmentDTO);

		return "lecturer_assignment_edit";
	}

	@RequestMapping(value = "/edit/{assignmentId}", method = RequestMethod.POST)
	public String editAssignment(
			@Valid @ModelAttribute("editAssignmentDTO") EditAssignmentDTO editAssignmentDTO,
			BindingResult result, @PathVariable String assignmentId,
			@PathVariable String openCourseId, @PathVariable String subjectId,
			Model model) {
		System.out.println("edit assignment");

		Assignment assignment = assignmentService
				.getAssignmentById(assignmentId);
		assignment.setAssignmentName(editAssignmentDTO.getAssignmentName());
		assignment.setDescription(editAssignmentDTO.getDescription());
		assignment.setEndDate(editAssignmentDTO.getEndDate());
		assignment.setMaxPoint(editAssignmentDTO.getMaxPoint());
		assignment.setStartDay(editAssignmentDTO.getStartDay());
		assignment.setTimeSubmitAllow(editAssignmentDTO.getTimeSubmitAllow());

		String fileName = editAssignmentDTO.getFile().getOriginalFilename();

		if (!"".equals(fileName)) {
			// add new file to DB
			MyFile file = new MyFile();
			file.setFileName(fileName);
			fileService.addFile(file);

			// write this file to directory
			MultipartFile mFile = editAssignmentDTO.getFile();

			try {
				mFile.transferTo(new java.io.File(FileUtil.getFileLocation(applicationContext) + "\\" + file.getFileId()));
			} catch (IllegalStateException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}

			// set this file to new Assignment
			assignment.setFile(file);
		}
		assignmentService.updateAssignment(assignment);

		return "redirect:../";
	}
	
	@RequestMapping(value = "/edit/{assignmentId}/removeFile", method = RequestMethod.GET)
	public String removeFile(@PathVariable String assignmentId,
			@PathVariable String openCourseId, @PathVariable String subjectId,
			Model model) {
		Assignment assignment = assignmentService.getAssignmentById(assignmentId);
		assignment.setFile(null);
		assignmentService.updateAssignment(assignment);
		
		return "redirect:";
	}

	@RequestMapping(value = "/{assignmentId}/class/{classId}", method = RequestMethod.GET)
	public String listSumittedAssignmentByClass(@PathVariable String classId,
			@PathVariable String assignmentId,
			@PathVariable String openCourseId, @PathVariable String subjectId,
			Model model) {

		model.addAttribute("classId", classId);

		return "lecturer_assignment_class";
	}

	@RequestMapping(value = "/{assignmentId}/grade/{submittedAssignmentId}", method = RequestMethod.GET)
	public String getGrade(@PathVariable String submittedAssignmentId,
			@PathVariable String assignmentId,
			@PathVariable String openCourseId, @PathVariable String subjectId,
			Model model) {

		Assignment assignment = assignmentService
				.getAssignmentById(assignmentId);
		SubmittedAssignment submittedAssignment = submittedAssigmentService
				.getSubmittedAssignment(submittedAssignmentId);

		model.addAttribute("assignment", assignment);
		model.addAttribute("submittedAssignment", submittedAssignment);
		model.addAttribute("file", assignment.getFile());
		model.addAttribute("studentFile", submittedAssignment.getFile());
		return "lecturer_assignment_grade";
	}

	@RequestMapping(value = "/{assignmentId}/grade/{submittedAssignmentId}", method = RequestMethod.POST)
	public String grade(
			@Valid @ModelAttribute("submittedAssignment") SubmittedAssignment submittedAssignment,
			BindingResult result,
			@PathVariable String submittedAssignmentId,
			@PathVariable String assignmentId,
			Model model) {
		
		if(result.hasErrors()) {
			return "redirect:" + submittedAssignmentId;
		}
		
		SubmittedAssignment sa = submittedAssigmentService.getSubmittedAssignment(submittedAssignmentId);
		Assignment assignment = assignmentService.getAssignmentById(assignmentId);
		
		if(submittedAssignment.getPoint() > assignment.getMaxPoint())
		{
			return "redirect:" + submittedAssignmentId;
		}
		
		sa.setPoint(submittedAssignment.getPoint());
		submittedAssigmentService.updateSubmittedAssignment(sa);
		
		return "redirect:"+submittedAssignmentId;
	}

	// AJAX

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping(value = "/listJSON")
	@ResponseBody
	public JsonObject getAssignmentList(@PathVariable int lecturerId,
			@PathVariable String openCourseId, @PathVariable String subjectId) {
		System.out.println("Lay assignment");

		String openCourseSubject = openCourseId + "_" + subjectId;

		OpenCourse_Subject subject = course_SubjectService
				.getCourse_Subject(openCourseSubject);

		List<Assignment> list = new ArrayList<Assignment>(
				subject.getListAssignment());

		JsonObject testJson = new JsonObject();
		testJson.setAaData(list);
		testJson.setiTotalRecords(list.size());
		testJson.setiTotalDisplayRecords(list.size());
		testJson.setsEcho(1);
		return testJson;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping(value = "/{assignmentId}/class/{classId}/listJSON")
	@ResponseBody
	public JsonObject getSubmittedAssignmentList(
			@PathVariable String assignmentId, @PathVariable String classId,
			@PathVariable int lecturerId, @PathVariable String openCourseId,
			@PathVariable String subjectId) {

		List<SubmittedAssignmentDTO> list = submittedAssigmentService
				.getListSubmittedAssignmentDTO(assignmentId, classId);

		JsonObject testJson = new JsonObject();
		testJson.setAaData(list);
		testJson.setiTotalRecords(list.size());
		testJson.setiTotalDisplayRecords(list.size());
		testJson.setsEcho(1);
		return testJson;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	@RequestMapping(value = "/info/{assignmentId}/classJSON")
	@ResponseBody
	public JsonObject getClassList(@PathVariable String assignmentId,
			@PathVariable int lecturerId, @PathVariable String openCourseId,
			@PathVariable String subjectId) {

		List<MyClass> all = openCourseService.getAllClass(openCourseId);
		List<MyClass> aList = new ArrayList<MyClass>(assignmentService
				.getAssignmentById(assignmentId).getListClass());

		List<ClassDTO> classList = new ArrayList<ClassDTO>();
		boolean flag = false;
		for (int i = 0; i < all.size(); i++) {
			for (int j = 0; j < aList.size(); j++) {
				if (all.get(i).getClassId().equals(aList.get(j).getClassId())) {
					flag = true;
				}
			}
			if (flag == true) {
				classList.add(new ClassDTO(all.get(i), true));
			} else {
				classList.add(new ClassDTO(all.get(i), false));
			}
			flag = false;
		}

		JsonObject testJson = new JsonObject();
		testJson.setAaData(classList);
		testJson.setiTotalRecords(classList.size());
		testJson.setiTotalDisplayRecords(classList.size());
		testJson.setsEcho(1);
		return testJson;
	}

	@RequestMapping(value = "/info/{testId}/update", method = RequestMethod.POST)
	@ResponseBody
	public String updateClassTest(@PathVariable String openCourseId,
			@PathVariable String testId, @RequestBody String listClass) {
		assignmentService.updateClasses(testId, listClass);
		return "OK";
	}

	@RequestMapping(value = "/delete/{assignmentId}", method = RequestMethod.GET)
	@ResponseBody
	public String deleteTest(@PathVariable String assignmentId,
			@PathVariable String openCourseId, @PathVariable String subjectId,
			Model model) {
		Assignment assignment = assignmentService
				.getAssignmentById(assignmentId);
		assignmentService.deleteAssignment(assignment);
		return "OK";
	}
}
